1. /* sxfbatn2.cpp by K.Tsuru */
  2. // function ID 5101 BRADIX
  3. /*************************************************************
  4. SDecimal class
  5. arctan(n/d) by series, n and d are integers.
  6. arctan(n/d) = (n/d){ 1 - (n^2/d^2)/3 + (n^4/d^4)/5 - .....}
  7. arctan(n/d) = (n/d) - (n^3/d^3)/3 + (n^5/d^5)/5 - .....
  8. Both series have the same precision.
  9. num < den <= ULONG_MAX/BRADIX = 131071
  10. den > BRADIX is Ok
  11. **************************************************************/
  12. #ifndef SN_H
  13. #include "sn.h"
  14. #endif
  15. static const char* const func = "Batan2";
  16. SDecimal Batan2(ulong num, ulong den){
  17. RealSize C;
  18. uint upPrec = 0;
  19. SDecimal t, res, delta;
  20. const ulong mt = t.SlOpMaxValue(); //=131071
  21. if(!num) return res; // res = 0
  22. if( (num >= den) || (den > mt) ) t.SetError(t.OUT_OF_RANGE, func, 5101);
  23. if(num < BRADIX){
  24. t.SetInt((int)num); XsDiv(t, den, res);
  25. } else {
  26. //When den > num >= BRADIX, the error increases by about two figures.
  27. //Then it temporally increases the effective figures.
  28. //Because (SN)*(SN) is not used here, it is not necessary to consider "proper".
  29. upPrec = 2u;
  30. C.SetEffFig(C.EffFigures()+upPrec);
  31. t.SetInt(1); XsDiv(t, den, res); // res = 1/den
  32. XsMult(res, num, res); // res = num/den < 1.0
  33. }
  34. t = res;
  35. //The square of denominator is less than "mt" or not.
  36. int dsq_lt_mt = ( (double)den*(double)den < (double)mt ) ? 1 : 0;
  37. ulong k = 1;
  38. if(dsq_lt_mt){
  39. ulong dsq = den*den, nsq = num*num; //square of denominator and numerator
  40. do {
  41. XsDiv(t, dsq, t); // t /= (den*den);
  42. if(nsq != 1) XsMult(t, nsq, t); // t *= num*num
  43. if( (k += 2) >= mt ){
  44. t.SetError(t.NOT_CONVERGE, func, -5101);
  45. break;
  46. }
  47. XsDiv(t, k, delta); // delta = t / k;
  48. if(k & 2) XXSub(res, delta, res); // res -= delta;
  49. else XXAdd(res, delta, res); // res += delta;
  50. } while( delta.Sign() );
  51. } else {
  52. int nsq_lt_mt = ( (double)num*(double)num < (double)mt ) ? 1 : 0;
  53. ulong nsq = nsq_lt_mt ? num*num : 0;
  54. do {
  55. XsDiv(t, den, t); XsDiv(t, den, t); // t /= (den*den);
  56. if(num != 1){ // t *= num*num
  57. if(nsq){
  58. XsMult(t, nsq, t);
  59. } else {
  60. XsMult(t, num, t); XsMult(t, num, t);
  61. }
  62. }
  63. if( (k += 2) >= mt ){
  64. t.SetError(t.NOT_CONVERGE, func, -5101);
  65. break;
  66. }
  67. XsDiv(t, k, delta); // delta = t / k;
  68. if(k & 2) XXSub(res, delta, res); // res -= delta;
  69. else XXAdd(res, delta, res); // res += delta;
  70. } while( delta.Sign() );
  71. }
  72. res.upToTerm = (k + 1)/2;
  73. if(upPrec){
  74. C.SetEffFig(0); t = res; //remove lower figures
  75. return t;
  76. }
  77. return res;
  78. }

sxfbatn2.cpp : last modifiled at 2008/12/04 17:13:14(2,650 bytes)
created at 2015/12/22 16:09:56
The creation time of this html file is 2017/10/27 15:45:59 (Fri Oct 27 15:45:59 2017).